import 'package:flutter/material.dart';
import 'package:flutter/scheduler.dart';
import 'package:player_plugin/video_definition.dart';

class VideoDefinitionSideBar extends StatefulWidget {
  VideoDefinitionSideBar({
    Key? key,
    this.itemList = const [],
    VideoDefinitionItemStyle? videoDefinitionItemStyle,
    this.onTapItem,
    this.onInit,
    this.defaultSource,
  })  : videoDefinitionItemStyle =
            videoDefinitionItemStyle ?? VideoDefinitionItemStyle(),
        super(key: key);

  final List<VideoDefinitionItem> itemList;
  final VideoDefinitionItemStyle videoDefinitionItemStyle;
  final ValueChanged<int>? onTapItem;
  final ValueChanged<AnimationController>? onInit;
  final dynamic defaultSource;

  @override
  State<VideoDefinitionSideBar> createState() => _VideoDefinitionSideBarState();
}

class _VideoDefinitionSideBarState extends State<VideoDefinitionSideBar>
    with SingleTickerProviderStateMixin {
  List<VideoDefinitionItem> get itemList => widget.itemList;

  VideoDefinitionItemStyle get videoDefinitionItemStyle =>
      widget.videoDefinitionItemStyle;

  ValueChanged<int>? get onTapItem => widget.onTapItem;

  ValueChanged<AnimationController>? get onInit => widget.onInit;

  dynamic get defaultSource => widget.defaultSource;

  late final AnimationController _controller = AnimationController(
    duration: const Duration(milliseconds: 300),
    vsync: this,
  );

  late final Animation<Offset> _offsetAnimation = Tween<Offset>(
    begin: const Offset(1, 0),
    end: const Offset(0, 0),
  ).animate(CurvedAnimation(
    parent: _controller,
    curve: Curves.easeInOut,
  ));

  HitTestBehavior? _behavior;

  int _selectedIndex = 0;

  @override
  void initState() {
    super.initState();
    onInit?.call(_controller);
    _controller.addListener(() {
      if (_controller.status == AnimationStatus.forward) {
        _behavior = HitTestBehavior.translucent;
        setState(() {});
      }
      if (_controller.status == AnimationStatus.reverse) {
        _behavior = null;
        setState(() {});
      }
    });
  }

  void changeDefaultIndex() {
    for (int i = 0; i < itemList.length; i++) {
      VideoDefinitionItem item = itemList[i];
      if (defaultSource == item.dataSource) {
        _selectedIndex = i;
        break;
      }
    }
  }

  @override
  void didUpdateWidget(covariant VideoDefinitionSideBar oldWidget) {
    super.didUpdateWidget(oldWidget);
    if (oldWidget.defaultSource != defaultSource ||
        oldWidget.itemList != itemList) {
      _selectedIndex = 0;
      SchedulerBinding.instance?.addPostFrameCallback((timeStamp) {
        changeDefaultIndex();
        setState(() {});
      });
    }
  }

  @override
  Widget build(BuildContext context) {
    double width = MediaQuery.of(context).size.width / 3;
    return GestureDetector(
      behavior: _behavior,
      onTap: () {
        _controller.reverse();
      },
      child: ClipRRect(
        child: Align(
          alignment: Alignment.centerRight,
          child: SlideTransition(
            position: _offsetAnimation,
            child: Container(
              width: width,
              color: Colors.black.withOpacity(0.6),
              alignment: Alignment.center,
              child: SingleChildScrollView(
                child: Column(
                  mainAxisAlignment: MainAxisAlignment.center,
                  crossAxisAlignment: CrossAxisAlignment.stretch,
                  children: _renderItems(),
                ),
              ),
            ),
          ),
        ),
      ),
    );
  }

  @override
  void dispose() {
    _controller.dispose();
    super.dispose();
  }

  List<Widget> _renderItems() {
    List<Widget> widgets = [];
    for (int i = 0; i < itemList.length; i++) {
      VideoDefinitionItem item = itemList[i];
      Widget widget = GestureDetector(
        behavior: HitTestBehavior.translucent,
        onTap: () async {
          _controller.reverse();
          if (_selectedIndex != i) {
            onTapItem?.call(i);
            _selectedIndex = i;
            setState(() {});
          }
        },
        child: Padding(
          padding: videoDefinitionItemStyle.padding,
          child: Text(
            item.title,
            textAlign: videoDefinitionItemStyle.textAlign,
            style: i == _selectedIndex
                ? videoDefinitionItemStyle.textStyle
                    .copyWith(color: videoDefinitionItemStyle.selectTextColor)
                : videoDefinitionItemStyle.textStyle,
          ),
        ),
      );
      widgets.add(widget);
    }
    return widgets;
  }
}
